package com.demo.convert.word2html.office2007;

import com.demo.convert.exception.Word2HtmlException;
import com.demo.convert.tool.FileTool;
import com.demo.convert.word2html.office2007.support.ChangeFontXHTMLConverter;
import com.demo.convert.word2html.office2007.support.EntityConvertContentHandlerFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.converter.core.BasicURIResolver;
import org.apache.poi.xwpf.converter.core.FileImageExtractor;
import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * @author fenggang.li
 * @create 2019-09-12 10:08
 */
@Slf4j
public class Word2HtmlConverter {
    /**
     * Convert word to html. <br/>
     * The same as {@link #convert(String, String, String, String)},
     * but "imageFileFolderPath" and "imageRelativePath" are null.
     *
     *
     * @param wordFilePath
     * @param htmlFilePath
     * @throws Word2HtmlException
     */
    public static void convert(String wordFilePath, String htmlFilePath) throws Word2HtmlException {
        convert(wordFilePath, htmlFilePath, null, null);
    }

    /**
     * Convert word to html. <br/>
     *
     * @param wordFilePath
     * @param htmlFilePath
     * @param imageFileFolderPath
     * @param imageRelativePath
     * @throws Word2HtmlException
     */
    public static void convert(String wordFilePath, String htmlFilePath, String imageFileFolderPath, String imageRelativePath) throws Word2HtmlException {
        /** source word */
        FileInputStream wordInputStream = null;
        try {
            wordInputStream = new FileInputStream(wordFilePath);
        } catch (FileNotFoundException e) {
            String message = "Work file not found. File path " + wordFilePath;
            throw new Word2HtmlException(message, e);
        }

        /** target html file */
        boolean parentFolderExist = FileTool.checkParentFolder(htmlFilePath);
        if (!parentFolderExist) {
            throw new RuntimeException("Parent folder doesn't exist. File path is {}" + htmlFilePath);
        }
        OutputStream htmlOutputStream = null;
        try {
            htmlOutputStream = new FileOutputStream(htmlFilePath);
        } catch (FileNotFoundException e) {
            String message = "Html file doesn't exist. File path is " + htmlFilePath;
            throw new Word2HtmlException(message, e);
        }


        convert(wordInputStream, htmlOutputStream, imageFileFolderPath, imageRelativePath);
    }

    /**
     * Convert word to html. <br/>
     * The same as {@link #convert(InputStream, OutputStream, String, String)},
     * but "imageFileFolderPath" and "imageRelativePath" are null.
     *
     * @param wordInputStream
     * @param htmlOutputStream
     * @throws Word2HtmlException
     */
    public static void convert(InputStream wordInputStream, OutputStream htmlOutputStream) throws Word2HtmlException {
        convert(wordInputStream, htmlOutputStream, null, null);
    }

    /**
     * Convert word to html
     *
     * @param wordInputStream
     * @param htmlOutputStream
     * @param imageFileFolderPath Folder used to save the images in the word.
     * @param imageRelativePath Relative path of the images in the html, used together with "imageFileFolderPath". For example, "images". Then the image src is "images/a.png".
     * @throws Word2HtmlException
     */
    public static void convert(InputStream wordInputStream, OutputStream htmlOutputStream, String imageFileFolderPath, String imageRelativePath) throws Word2HtmlException {
        /** Options */
        XHTMLOptions options = XHTMLOptions.create();

        if (!Objects.isNull(imageFileFolderPath) && !imageFileFolderPath.isEmpty()) {
            File imageFileFolder = new File(imageFileFolderPath);
            if (!imageFileFolder.exists()) {
                throw new Word2HtmlException("Image folder not exists. Folder path is " + imageFileFolderPath);
            }
            options.setExtractor(new FileImageExtractor(imageFileFolder));
            // html中图片的路径 相对路径
            options.URIResolver(new BasicURIResolver(imageRelativePath));
        }
        // 忽略未使用的style
        options.setIgnoreStylesIfUnused(false);
        // html片段
        options.setFragment(false);
        // EntityConvertContentHandlerFactory
        options.setContentHandlerFactory(new EntityConvertContentHandlerFactory());

        /** source word */
        XWPFDocument wordDocument = null;
        try {
            wordDocument = new XWPFDocument(wordInputStream);
        } catch (IOException e) {
            throw new Word2HtmlException("Reading word failed", e);
        }

        /** target html file */
        OutputStreamWriter htmlWriter = null;
        try {
            htmlWriter = new OutputStreamWriter(htmlOutputStream, StandardCharsets.UTF_8.name());
        } catch (UnsupportedEncodingException e) {
            throw new Word2HtmlException("Charset UTF8 is not supported.", e);
        }


        /** convert */
        ChangeFontXHTMLConverter converter = ChangeFontXHTMLConverter.getInstance();
        try {
            converter.convert(wordDocument, htmlWriter, options);
        } catch (IOException e) {
            throw new Word2HtmlException("Convert failed.", e);
        }
    }
}
